package jmine.tec.proxy;

import jmine.tec.proxy.chain.ChainElement;
import jmine.tec.proxy.chain.InvocationChain;


/**
 * @author takeshi
 * 
 */
public class SynchronizedChainElement implements ChainElement {

    private final Object lock;

    /**
     * 
     * @param lock
     *            the lock
     */
    public SynchronizedChainElement(final Object lock) {
        super();
        this.lock = lock;
    }

    /**
     * 
     */
    public SynchronizedChainElement() {
        this(new Object());
    }

    /**
     * @param chain
     *            chain
     * @return Object
     * @throws Throwable
     *             t
     * @see br.com.maps.util.proxy.chain.ChainElement#aroundInvoke(br.com.maps.util.proxy.chain.InvocationChain)
     */
    public Object aroundInvoke(final InvocationChain chain) throws Throwable {
        final Object toUse;
        if (lock == null) {
            if (chain.getBean() == null) {
                toUse = chain.getProxyObject();
            } else {
                toUse = chain.getBean();
            }
        } else {
            toUse = lock;
        }

        synchronized (toUse) {
            return chain.proceed();
        }
    }

}
